home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cxref200.zip / CXREF.C < prev    next >
Text File  |  1993-01-04  |  17KB  |  603 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3.  
  4. #define NestMax 10
  5.  
  6. char CR = 0x0D;
  7. char IDChar[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_";
  8. char TINCLUDE[] = "#include";
  9. char *Reserved[] = {
  10.         "auto",
  11.         "break",
  12.         "case",
  13.         "char",
  14.         "continue",
  15.         "default",
  16.         "do",
  17.         "double",
  18.         "else",
  19.         "entry",
  20.         "extern",
  21.         "float",
  22.         "for",
  23.         "goto",
  24.         "if",
  25.         "int",
  26.         "long",
  27.         "register",
  28.         "return",
  29.         "short",
  30.         "sizeof",
  31.         "static",
  32.         "struct",
  33.         "switch",
  34.         "typedef",
  35.         "union",
  36.         "unsigned",
  37.         "void",
  38.         "while"
  39.         };
  40.  
  41. typedef struct {
  42.     int AX, BX, CX, DX, SI, DI;
  43.     } RegPack;
  44.  
  45. typedef struct {
  46.     FILE *ID;
  47.     char Name[64];
  48.     int Lnno;
  49.     char InsertChar;
  50.     int EndFile, First, Print;
  51.     } FileDef;
  52.  
  53. typedef struct LR {
  54.     struct LR *Next;
  55.     int Key;
  56.     char Code;
  57.     } LineRec;
  58.  
  59. typedef struct {
  60.     LineRec *First, *Current;
  61.     } LineQueueRec;
  62.  
  63. typedef struct {
  64.     char *Key;
  65.     LineQueueRec *LineList;
  66.     } WordRec;
  67.  
  68. typedef struct TR {
  69.     struct TR *Left, *Right;
  70.     WordRec *Ref;
  71.     } TreeRec;
  72.  
  73. int PageNum, PageLn;
  74. TreeRec *Root;
  75. FileDef MainFile, IncludeFile, InFile;
  76. FILE *Output;
  77. int TotalLn, ChIndex;
  78. int Listing, StdFlag, IncludeFlag;
  79. int NestUp, NestDn, NestLvl;
  80. int Tabs;
  81. char Token[30], Path[64], IncludePath[64];
  82. int i;
  83. char *FDate, *FTime;
  84. char Today[30];
  85. char *OutFileName[64];
  86. char Ch;
  87. int UnGetCount = 0;
  88. char UnGot = ' ';
  89. char Line[255];
  90.  
  91. main (argc, argv)
  92. int argc;
  93. char *argv[];
  94. {
  95.     void Init(), GetFileDate(), Header(), GetLiteral(), GetIncludeFile();
  96.     void GetCharLiteral(), GetComment(), GetToken(), PrintLine(), AddQueue();
  97.     void Concordance(), Usage();
  98.     FILE *fopen();
  99.     char GetChar(), *index();
  100.  
  101.     Init();
  102.     if (argc < 2) Usage();
  103.     else {
  104.         for (i = 1; i < argc; i++) {
  105.             strcpy(Token, argv[i]);
  106.             if (Token[0] == '-') {
  107.                 UpperCase(Token);
  108.                 if (strcmp(Token, "-NL") == 0) Listing = FALSE;
  109.                 else if (strcmp(Token, "-NS") == 0) StdFlag = FALSE;
  110.                 else if (strcmp(Token, "-NI") == 0) IncludeFlag = FALSE;
  111.                 else if (Token[1] == 'T') {
  112.                     if (i+1 < argc) Tabs = atoi(argv[++i]);
  113.                     else fprintf(stderr, "Invalid Tab option\n");
  114.                     }
  115.                 else if (Token[1] == 'I') {
  116.                     if (i+1 < argc) {
  117.                         strcpy(IncludePath, argv[++i]);
  118.                         if (IncludePath[strlen(IncludePath)-1] != "\\")
  119.                             strcat(IncludePath, "\\");
  120.                         }
  121.                     else fprintf(stderr, "Invalid Include Path option\n");
  122.                     }
  123.                 else {
  124.                     fprintf(stderr, "Invalid option: %s\n", argv[i]);
  125.                     }
  126.                 }
  127.             else if (strlen(InFile.Name) == 0) strcpy(InFile.Name, argv[i]);
  128.             else if (strlen(OutFileName) == 0) strcpy(OutFileName, argv[i]);
  129.             else {
  130.                 fprintf(stderr, "Invalid parameter or too many file names: %s\n", argv[i]);
  131.                 Abort();
  132.                 }
  133.             }
  134.         }
  135.     if (strlen(InFile.Name) == 0) {
  136.         fprintf(stderr, "I have nothing to do!  No input file specified.\n");
  137.         Abort();
  138.         }
  139.     if (index(InFile.Name, '.') == NULL) strcat(InFile.Name, ".C");
  140.     for (i = strlen(InFile.Name); i >= 0; i--) {
  141.         if ((InFile.Name[i] == '\\') || (InFile.Name[i] == '/') || (InFile.Name[i] == ':')) break;
  142.         }
  143.     if (i < 0) strcpy(Path, "");
  144.     else {
  145.         strncpy(Path, InFile.Name, i+1);
  146.         Path[i+1] = '\0';
  147.         }
  148.     if (strlen(OutFileName) == 0) {
  149.         strcpy(OutFileName, InFile.Name);
  150.         *index(OutFileName, '.') = 0x00;
  151.         }
  152.     if (index('.', OutFileName) == NULL) strcat(OutFileName, ".LST");
  153.     if ((InFile.ID = fopen(InFile.Name, "r")) == NULL) {
  154.         fprintf(stderr, "I can't find input file: %s\n", InFile.Name);
  155.         Abort();
  156.         }
  157.     InFile.Lnno = 0; InFile.EndFile = FALSE; InFile.Print = TRUE;
  158.     InFile.First = TRUE;
  159.     if ((Output = fopen(OutFileName, "w")) == NULL) {
  160.         fprintf(stderr, "I can't create output file: %s\n", OutFileName);
  161.         Abort();
  162.         }
  163.     MainFile = InFile; ChIndex = 0;
  164.     GetFileDate(InFile.ID->_file, &FDate, &FTime);
  165.     strcpy(Today," Date: ");
  166.     strcat(Today, FDate); strcat(Today, " @ "); strcat(Today, FTime);
  167.  
  168.     if (Listing) Header();
  169.     while (!MainFile.EndFile) {
  170.         while (!InFile.EndFile) {
  171.             Ch = GetChar();
  172.             if (Ch == '"') GetLiteral();
  173.             else if ((Ch == '#') && IncludeFlag) GetIncludeFile();
  174.             else if (Ch == '\'') GetCharLiteral();
  175.             else if (Ch == '/') GetComment();
  176.             else if (index(IDChar, Ch) != NULL) GetToken();
  177.             else if (Ch == '{') {
  178.                 if (NestLvl == NestMax) fprintf(stderr, "---- Too many levels\n");
  179.                 else {
  180.                     NestLvl++; NestUp = TRUE;
  181.                     }
  182.                 }
  183.             else if (Ch == '}') {
  184.                 if (NestLvl == 0) fprintf(stderr, "---- Nesting Error");
  185.                 else {
  186.                     NestLvl--; NestDn = TRUE;
  187.                     }
  188.                 }
  189.             }
  190.         PrintLine();
  191.         if (InFile.InsertChar != ' ') {
  192.             fclose(InFile.ID);
  193.             InFile = MainFile; ChIndex = 0;
  194.             }
  195.         else MainFile = InFile;
  196.         }
  197.     Header(); fprintf(stderr, "\n");
  198.     fprintf(stderr, "Writing Cross Reference\n");
  199.     Concordance(Root);
  200.     fclose(Output);
  201.     fprintf(stderr, "    Total Pages= %d\n", PageNum);
  202.     }
  203.  
  204. void BackCh (Ch)
  205. char Ch;
  206. {
  207.     UnGot = Ch; UnGetCount = 1;
  208.     }
  209.  
  210. char GetChar () {
  211.     char Ch, InLine[255];
  212.     int i, j;
  213.  
  214.     if (UnGetCount) {
  215.         UnGetCount = 0; return(UnGot);
  216.         }
  217.     if (InFile.First) {
  218.         InFile.ID = fopen(InFile.Name, "r");
  219.         InFile.First = FALSE;
  220.         }
  221.     if (ChIndex == 0) {
  222.         if (!InFile.EndFile) {
  223.             if (InFile.Print) {
  224.                 InFile.Print = FALSE; fprintf(stderr, "\n");
  225.                 fprintf(stderr, "Line= %4d%c Total Lines= %4d  ", InFile.Lnno,
  226.                         InFile.InsertChar, TotalLn);
  227.                 if (InFile.InsertChar != ' ') fprintf(stderr, "%13s", "");
  228.                 fprintf(stderr, "%s", InFile.Name); fputc(CR, stderr);
  229.                 }
  230.             else PrintLine();
  231.             fgets(InLine, 255, InFile.ID);
  232.             i = j = 0;
  233.             while (InLine[i]) {
  234.                 if (InLine[i] == '\t') {
  235.                     do Line[j++] = ' ';
  236.                     while (j % Tabs);
  237.                     }
  238.                 else Line[j++] = InLine[i];
  239.                 ++i;
  240.                 }
  241.             Line[j] = 0x00;
  242.             if (feof(InFile.ID)) InFile.EndFile = TRUE;
  243.             else {
  244.                 Line[strlen(Line)-1] = 0x00;
  245.                 InFile.Lnno++; TotalLn++;
  246.                 GotoXY(6, WhereY()); fprintf(stderr, "%4d%c",
  247.                        InFile.Lnno, InFile.InsertChar);
  248.                 GotoXY(25, WhereY()); fprintf(stderr, "%4d", TotalLn);
  249.                 NestUp = FALSE; NestDn = FALSE;
  250.                 ChIndex = 1;
  251.                 }
  252.             }
  253.         }
  254.     if (!InFile.EndFile) {
  255.         if (ChIndex <= strlen(Line)) Ch = Line[ChIndex++- 1];
  256.         else {
  257.             Ch = ' '; ChIndex = 0;
  258.             }
  259.         }
  260.     return(Ch);
  261.     }
  262.  
  263. void Init () {
  264.     printf("C Cross Reference: Version 2.00  June 25, 1986\n\n");
  265.     PageNum = 0; Root = NULL; InFile.InsertChar = ' '; TotalLn = 0;
  266.     IncludeFile.InsertChar = '@';
  267.     Listing = TRUE; StdFlag = TRUE; IncludeFlag = TRUE;
  268.     NestUp = FALSE; NestDn = FALSE; NestLvl = 0; Tabs = 4;
  269.     IncludePath[0] = 0x00;
  270.     }
  271.  
  272. int UpperCase (Str)
  273. char *Str;
  274. {
  275.     int i;
  276.  
  277.     for (i = 0; i < strlen(Str); i++)
  278.         if (islower(Str[i])) Str[i] = (char) toupper(Str[i]);
  279.     }
  280.  
  281. void GetFileDate (Handle, Date, Time)
  282. int Handle;
  283. char **Date, **Time;
  284. {
  285.     char *malloc();
  286.  
  287.     struct {
  288.        int AX, BX, CX, DX, SI, DI;
  289.        } Regs;
  290.  
  291.     Regs.AX = 0x5700; Regs.BX = Handle;
  292.     intdos(&Regs, &Regs);
  293.     *Date = malloc(9);
  294.     sprintf(*Date, "%02d-%02d-%02d", ((Regs.DX >> 5) & 0x0F), (Regs.DX & 0x1F),
  295.             (Regs.DX >> 9));
  296.     *Time = malloc(9);
  297.     sprintf(*Time, "%02d:%02d:%02d", (Regs.CX >> 11), ((Regs.CX >> 5) & 0x3F),
  298.             (Regs.CX & 0x1F));
  299.     }
  300.  
  301. void Header () {
  302.     PageNum++;
  303.     fputc(0x0C, Output);             /*  Form Feed */
  304.     fprintf(Output, "%-48s", MainFile.Name);
  305.     fprintf(Output, "Block Structure and Cross Reference");
  306.     fprintf(Output, "%29s   Page %3d", Today, PageNum);
  307.     fprintf(Output, "\n\n\n");
  308.     PageLn = 60;
  309.     }
  310.  
  311. void GetLiteral () {
  312.     char Ch;
  313.  
  314.     do {
  315.         Ch = GetChar();
  316.         if (Ch == '\\') {
  317.             Ch = GetChar(); Ch = GetChar();
  318.             }
  319.         }
  320.     while ((!InFile.EndFile) && (Ch != '"'));
  321.     }
  322.  
  323. void GetIncludeFile () {
  324.     extern int stricmp();
  325.     void PrintLine(), GetToken();
  326.  
  327.     int i, OK;
  328.     char DeLim;
  329.     char Temp[64];
  330.  
  331.     GetToken();
  332.     if (stricmp(Token, TINCLUDE) == 0) {
  333.         OK = TRUE;
  334.         while ((!InFile.EndFile) && (Ch == ' ')) Ch = GetChar();
  335.         switch (Ch) {
  336.             case '"': DeLim = Ch;
  337.                       break;
  338.             case '<': DeLim = '>';
  339.                       break;
  340.             default:  DeLim = ' ';
  341.             }
  342.         for (i=0; ((!InFile.EndFile) && ((Ch = GetChar()) != DeLim)); i++) {
  343.             Temp[i] = Ch;
  344.             }
  345.         Temp[i] = 0x00;
  346.         if (InFile.InsertChar == 'Z') {
  347.             fprintf(stderr, "Too many include files\n");
  348.             OK = FALSE;
  349.             }
  350.         else {
  351.             if (DeLim == '"') {
  352.                 strcpy(IncludeFile.Name, Path); strcat(IncludeFile.Name, Temp);
  353.                 }
  354.             else {
  355.                 strcpy(IncludeFile.Name, IncludePath);
  356.                 strcat(IncludeFile.Name, Temp);
  357.                 }
  358.             IncludeFile.InsertChar++;
  359.             IncludeFile.Lnno = 0; IncludeFile.EndFile = FALSE;
  360.             IncludeFile.Print = TRUE; IncludeFile.First = TRUE;
  361.             if ((IncludeFile.ID = fopen(IncludeFile.Name, "r")) == NULL) {
  362.                 fprintf(stderr, "\nCan't find include file: %s\n", IncludeFile.Name);
  363.                 OK = FALSE;
  364.                 }
  365.             }
  366.         PrintLine();
  367.         if (OK) {
  368.             MainFile = InFile; MainFile.Print = TRUE;
  369.             InFile = IncludeFile;
  370.             ChIndex = 0;
  371.             }
  372.         }
  373.     }
  374.  
  375. void PrintLine () {
  376.     void FillLine();
  377.  
  378.     int Column;
  379.  
  380.     if (Listing) {
  381.         fprintf(Output, "%4d%c    ", InFile.Lnno, InFile.InsertChar);
  382.         for (Column=0; Column < NestLvl-1; Column++) fprintf(Output,"|  ");
  383.         if (NestLvl > 0) {
  384.             if (NestUp || NestDn) {
  385.                 if (NestDn) {
  386.                     fprintf(Output, "|  ");
  387.                     fprintf(Output, "E--");
  388.                     for (Column=NestLvl+1; Column < NestMax; Column++)
  389.                         fprintf(Output, "---");
  390.                     }
  391.                 else {
  392.                     fprintf(Output, "B--");
  393.                     for (Column=NestLvl; Column < NestMax; Column++)
  394.                         fprintf(Output, "---");
  395.                     }
  396.                 FillLine(Line);
  397.                 }
  398.             else {
  399.                 fprintf(Output, "|  ");
  400.                 for (Column=NestLvl; Column < NestMax; Column++)
  401.                     fprintf(Output, "   ");
  402.                 }
  403.             }
  404.         else if (NestDn) {
  405.             fprintf(Output, "E--");
  406.             for (Column=1; Column<NestMax; Column++) fprintf(Output, "---");
  407.             FillLine(Line);
  408.             }
  409.         else for (Column=0; Column<NestMax; Column++) fprintf(Output, "   ");
  410.         fprintf(Output, "%s\n", Line);
  411.         PageLn--;
  412.         if (PageLn <= 0) Header();
  413.         }
  414.     }
  415.  
  416. void FillLine (Line)
  417. char *Line;
  418. {
  419.     int i;
  420.  
  421.     for(i=0; i<strlen(Line) && Line[i] == ' '; i++) Line[i] = '-';
  422.     }
  423.  
  424.  
  425. void GetToken () {
  426.     TreeRec *BinaryTree();
  427.  
  428.     int j;
  429.  
  430.     j = 0;
  431.     do {
  432.         Token[j] = Ch; j++; Ch = GetChar();
  433.         }
  434.     while ((index(IDChar, Ch) != NULL) && (!InFile.EndFile));
  435.     Token[j] = 0x00;
  436.     if (StdFlag) Root = BinaryTree(Root);
  437.     else if (!BinarySearch(Token, Reserved, 29)) Root = BinaryTree(Root);
  438.     }
  439.  
  440. void GetComment () {
  441.     char Ch;
  442.  
  443.     if (!InFile.EndFile) Ch = GetChar();
  444.     if ((!InFile.EndFile) && (Ch == '*')) {
  445.         while ((!InFile.EndFile) && (Ch != '/')) {
  446.             while((!InFile.EndFile) && (Ch != '*')) Ch = GetChar();
  447.             Ch = GetChar();
  448.             }
  449.         }
  450.     else BackCh(Ch);
  451.     }
  452.     
  453. void GetCharLiteral () {
  454.     char Ch;
  455.  
  456.     do {
  457.         Ch = GetChar();
  458.         if (Ch == '\\') {
  459.             Ch = GetChar(); Ch = GetChar();
  460.             }
  461.         }
  462.     while ((!InFile.EndFile) && (Ch != '\''));
  463.     }
  464.  
  465. int BinarySearch (T, A, Num)
  466. char *T, *A[];
  467. int Num;
  468. {
  469.     extern int stricmp();
  470.     int i, j, k, Result;
  471.  
  472.     i = 0; j = Num;
  473.     do {
  474.         k = (i + j) / 2;
  475.         Result = stricmp(A[k], T);
  476.         switch (Result) {
  477.             case -1: i = ++k;
  478.                      break;
  479.             case  1: j = --k;
  480.                      break;
  481.             default: break;
  482.             }
  483.         }
  484.     while ((Result != 0) && (i <= j));
  485.     if (Result == 0) return(TRUE);
  486.     else return(FALSE);
  487.     }
  488.  
  489. TreeRec *BinaryTree (wl)
  490. TreeRec *wl;
  491. {
  492.     extern int stricmp();
  493.  
  494.     TreeRec *w;
  495.  
  496.     w = wl;
  497.     if (w == NULL) {
  498.         w = (TreeRec *) malloc(sizeof(*w));
  499.         w->Ref = (WordRec *) malloc(sizeof(*(w->Ref)));
  500.         w->Left = w->Right = NULL;
  501.         wl = w;
  502.         w->Ref->Key = malloc(strlen(Token)+1); strcpy(w->Ref->Key, Token);
  503.         w->Ref->LineList = (LineQueueRec *) malloc(sizeof(*(w->Ref->LineList)));
  504.         w->Ref->LineList->First = NULL;
  505.         AddQueue(w->Ref->LineList);
  506.         }
  507.     else {
  508.         switch (stricmp(Token, w->Ref->Key)) {
  509.             case -1: w->Left = BinaryTree(w->Left);
  510.                      break;
  511.             case  1: w->Right = BinaryTree(w->Right);
  512.                      break;
  513.             case  0: AddQueue(w->Ref->LineList);
  514.                      break;
  515.             }
  516.         }
  517.     return(w);
  518.     }
  519.  
  520.  
  521. void AddQueue (Queue)
  522. LineQueueRec *Queue;
  523. {
  524.     LineRec *w;
  525.  
  526.     w = (LineRec *) malloc(sizeof(LineRec));
  527.     if (Queue->First == NULL) Queue->First = w;
  528.     else Queue->Current->Next = w;
  529.     Queue->Current = w;
  530.     w->Next = NULL; w->Key = InFile.Lnno; w->Code = InFile.InsertChar;
  531.     }
  532.  
  533. char *FillString (Str, Size, Char)
  534. char *Str, Char;
  535. int   Size;
  536. {
  537.     char Temp[255];
  538.     int l;
  539.  
  540.     strcpy(Temp, Str);
  541.     if (strlen(Temp) < Size) {
  542.         strcat(Temp, " ");
  543.         l = strlen(Temp);
  544.         while (l < Size) Temp[l++] = Char;
  545.         Temp[l] = 0x00;
  546.         }
  547.     return(Temp);
  548.     }
  549.  
  550. void Concordance (T)
  551. TreeRec *T;
  552. {
  553.     char *FillString();
  554.  
  555.     static char OldCh = 'A';
  556.     LineRec *P;
  557.     int i;
  558.  
  559.     if (T != NULL) {
  560.         Concordance(T->Left);
  561.         if (toupper(T->Ref->Key[0]) != OldCh) {
  562.             fprintf(Output, "\n"); PageLn--;
  563.             if (PageLn <= 0) Header();
  564.             OldCh = toupper(T->Ref->Key[0]);
  565.             }
  566.         fprintf(Output, "%s ", FillString(T->Ref->Key, 26, '.'));
  567.         if (!BinarySearch(T->Ref->Key, Reserved, 29)) fprintf(Output, "%c", ' ');
  568.         else fprintf(Output, "%c", 'R');
  569.         P = T->Ref->LineList->First; i = 0;
  570.         while (P != NULL) {
  571.             if (i >= 17) {
  572.                 fprintf(Output, "\n"); i = 0;
  573.                 PageLn--;
  574.                 if (PageLn <= 0) Header();
  575.                 fprintf(Output, "%28s", " ");
  576.                 }
  577.             fprintf(Output, "%4d%c", P->Key, P->Code);
  578.             i++;
  579.             if (i < 17) fprintf(Output, "%s", " ");
  580.             P = P->Next;
  581.             }
  582.         if (i > 0) {
  583.             fprintf(Output, "\n");
  584.             PageLn--;
  585.             if (PageLn <= 0) Header();
  586.             }
  587.         Concordance(T->Right);
  588.         }
  589.     }
  590.  
  591. void Usage () {
  592.  
  593.     fprintf(stderr, "USAGE: cxref input_file_spec [output_file_spec] [options]\n\n");
  594.     fprintf(stderr, "\t-NL\tSuppress production of listing\n");
  595.     fprintf(stderr, "\t-NS\tSuppress cross reference of C key words\n");
  596.     fprintf(stderr, "\t-NI\tSuppress analysis of #include files\n\n");
  597.     fprintf(stderr, "\t-I <path> Provide path for #include <file> files\n");
  598.     fprintf(stderr, "\t-T <n>    Provide the tab stop value for tab expansion\n");
  599.     exit();
  600.     }
  601.  
  602.  
  603.